/*
	Simple Software Renderer (SSRenderer)
	Copyright (C) 2007 Piotr Orzechowski <piotr.orzechowski@gmail.com>

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef _SSROBJECT_H
#define _SSROBJECT_H

#include <assert.h>
#include "./SSRTypes.h"

namespace ssr
{

// If the pointer is not null, increase a reference counter of the pointed object.
#define SSR_ADDREF(p)   {if (p != NULL) {(p)->AddRef();} }

// If the pointer is not null, the object it is pointing to is released and the pointer is set to null to ease debugging and to make sure it is not released again using SAFE_RELEASE().
#define SSR_RELEASE(p)	{if (p != NULL) {(p)->Release(); p = 0; }}

/**
	ISSRObject is a base class for most classes in the library.
	It provides a reference counting pattern and helps in tracking
	memory flaws in a debug mode.
*/
class ISSRObject
{
public:

	/**
		Increases the reference counter.
	*/
	void AddRef()
	{
		++m_RefCounter;
	}

	/**
		Decreases the reference counter and when it hits 0 deletes the object.
	*/
	void Release()
	{
		if (--m_RefCounter == 0)
		{
			delete this;
		}
	}

	/**
		Returns NULL-ended string containing name of the class.

		@return NULL-ended string containing name of the class
	*/
	virtual const u8* ClassName() = 0;

protected:

	/**
		Default constructor initializes reference counter to 0
	*/
	ISSRObject() : m_RefCounter(1)
	{
	}

	virtual ~ISSRObject()
	{
		assert(m_RefCounter == 0 && "Referece counting failed!");
	}

private:

	/**
		Private copy-operator to avoid object copying.
	*/
	ISSRObject(ISSRObject&) {}

	/**
		Private assignment-operator to avoid object copying.
	*/
	ISSRObject &operator =(ISSRObject&) { return *this; }

	u32	m_RefCounter;
};

} // namespace

#endif
